/*
 * gpio_utils.c
 * 
 * GPIO实用工具函数实现，包括按键检测和呼吸灯效果
 */

#include "gpio_utils.h"
#include <stdio.h>
#include <unistd.h> // 显式包含unistd.h以解决usleep函数的隐式声明警告
#include <time.h>   // 显式包含time.h以解决clock_gettime函数的隐式声明警告

// 获取系统当前时间（毫秒）
uint32_t get_system_time_ms(void)
{
    struct timespec ts;
    int ret;
    
    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
    if (ret < 0) {
        perror("clock_gettime failed");
        return 0;
    }
    
    return (uint32_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
}

// 初始化按键状态
void key_init(key_state_t *state, int gpio_num)
{
    if (state == NULL) {
        return;
    }
    
    state->gpio_num = gpio_num;
    state->prev_state = 1; // 默认初始状态为释放（假设按键为上拉输入）
    state->press_start_time = 0;
    state->release_time = 0;
    state->click_count = 0;
    state->state = KEY_STATE_IDLE;
}

// 按键检测算法
uint8_t key_detect(key_state_t *state)
{
    int current_state = 0;
    uint8_t event = KEY_EVENT_NONE;
    uint32_t current_time = get_system_time_ms();
    
    if (state == NULL) {
        return KEY_EVENT_NONE;
    }
    
    // 读取GPIO状态（假设1为释放，0为按下）
    if (gpio_get_value(state->gpio_num, &current_state) < 0) {
        return KEY_EVENT_NONE;
    }
    
    // 按键状态变化检测
    switch (state->state) {
        case KEY_STATE_IDLE:
            if (current_state == 0 && state->prev_state == 1) { // 按键按下
                state->press_start_time = current_time;
                state->state = KEY_STATE_PRESSED;
                state->prev_state = current_state;
            }
            break;
            
        case KEY_STATE_PRESSED:
            if (current_state == 1) { // 按键释放
                state->release_time = current_time;
                state->state = KEY_STATE_RELEASED;
                state->prev_state = current_state;
                state->click_count++;
            } else if (current_time - state->press_start_time > KEY_LONG_PRESS_THRESHOLD_MS) { // 长按检测
                event = KEY_EVENT_LONG_PRESS;
                state->state = KEY_STATE_IDLE;
                state->click_count = 0;
            }
            break;
            
        case KEY_STATE_RELEASED:
            if (current_state == 0) { // 再次按下（双击检测）
                state->press_start_time = current_time;
                state->state = KEY_STATE_PRESSED;
                state->prev_state = current_state;
            } else if (current_time - state->release_time > KEY_CLICK_INTERVAL_MS) { // 点击间隔超时，判断点击次数
                if (state->click_count == 1) {
                    event = KEY_EVENT_SHORT_PRESS;
                } else if (state->click_count == 2) {
                    event = KEY_EVENT_DOUBLE_CLICK;
                } else if (state->click_count == 6) {
                    event = KEY_EVENT_SIX_CLICK;
                }
                
                state->state = KEY_STATE_IDLE;
                state->click_count = 0;
            }
            break;
            
        default:
            state->state = KEY_STATE_IDLE;
            break;
    }
    
    return event;
}

// 设置LED亮度（模拟PWM）
int led_set_brightness(int gpio_num, uint8_t brightness)
{
    int i;
    int on_time, off_time;
    
    // 检查参数有效性
    // 修复类型限制警告：直接检查原始brightness值，然后再进行掩码操作
    if (brightness > 255) {
        brightness = 255;
    }
    brightness &= 0xFF;
    
    // 如果亮度为0，直接关闭LED
    if (brightness == 0) {
        return gpio_set_value(gpio_num, 0);
    }
    
    // 如果亮度为255，直接打开LED
    if (brightness == 255) {
        return gpio_set_value(gpio_num, 1);
    }
    
    // 模拟PWM，周期为10ms（100Hz）
    on_time = (brightness * 10) / 255;  // 计算ON时间（毫秒）
    off_time = 10 - on_time;            // 计算OFF时间（毫秒）
    
    // 执行10个周期的PWM
    for (i = 0; i < 10; i++) {
        if (gpio_set_value(gpio_num, 1) < 0) {
            return -1;
        }
        usleep(on_time * 1000);  // 等待ON时间
        
        if (gpio_set_value(gpio_num, 0) < 0) {
            return -1;
        }
        usleep(off_time * 1000); // 等待OFF时间
    }
    
    return 0;
}

// 实现呼吸灯效果
int led_breath(int gpio_num, breath_effect_t effect, uint32_t duration_ms)
{
    uint32_t start_time = get_system_time_ms();
    uint32_t current_time;
    uint32_t cycle_time;
    float phase;
    float brightness;
    
    // 根据效果选择周期时间
    switch (effect) {
        case BREATH_EFFECT_SLOW:
            cycle_time = BREATH_CYCLE_SLOW;
            break;
        case BREATH_EFFECT_FAST:
            cycle_time = BREATH_CYCLE_FAST;
            break;
        case BREATH_EFFECT_PULSE:
            cycle_time = BREATH_CYCLE_PULSE;
            break;
        case BREATH_EFFECT_WAVE:
            cycle_time = BREATH_CYCLE_WAVE;
            break;
        default:
            cycle_time = BREATH_CYCLE_SLOW;
            break;
    }
    
    // 执行呼吸灯效果直到达到持续时间
    while ((current_time = get_system_time_ms()) - start_time < duration_ms) {
        // 计算当前相位
        phase = (float)((current_time - start_time) % cycle_time) / cycle_time;
        
        // 根据效果计算亮度
        switch (effect) {
            case BREATH_EFFECT_SLOW:
                // 平缓呼吸：使用完整的正弦曲线
                brightness = (sin(phase * 2 * M_PI - M_PI_2) + 1) / 2;
                break;
            case BREATH_EFFECT_FAST:
                // 急促呼吸：使用快速变化的正弦曲线
                brightness = (sin(phase * 4 * M_PI - M_PI_2) + 1) / 2;
                break;
            case BREATH_EFFECT_PULSE:
                // 脉冲效果：使用更陡的曲线
                brightness = phase < 0.5 ? phase * 2 : (1 - phase) * 2;
                break;
            case BREATH_EFFECT_WAVE:
                // 波浪效果：使用双正弦波叠加
                brightness = (sin(phase * 2 * M_PI - M_PI_2) + 0.5 * sin(phase * 6 * M_PI - M_PI_2) + 1.5) / 3;
                break;
            default:
                brightness = 0.5;
                break;
        }
        
        // 设置亮度
        if (led_set_brightness(gpio_num, (uint8_t)(brightness * 255)) < 0) {
            return -1;
        }
        
        // 短暂延时以降低CPU占用
        usleep(10000); // 10ms
    }
    
    return 0;
}